home *** CD-ROM | disk | FTP | other *** search
/ The PC-SIG Library 9 / The PC-SIG Library on CD ROM - Ninth Edition.iso / 1501_600 / DISK1533 / DISK1533.ZIP / TAIL.C < prev    next >
Text File  |  1989-02-22  |  4KB  |  174 lines

  1. #include <stdio.h>
  2. #include <local.h>
  3.  
  4. #define    LINSIZ    128    /* max bytes in 1 line */
  5. #define    DEFAULT    10    /* default lines used  */
  6.  
  7. #define max(x, y)  ((x) > (y) ? (x) : (y))
  8.  
  9. /*
  10.  * TAIL.C - the tail of a file, works like a filter if there are no
  11.  * files specified on the command line, the unix utility does not
  12.  * allow wildcards in the tail and tail commands, so they are not
  13.  * supported, usage like: tail {/n} {file file ... }
  14.  */
  15.  
  16. static    char *Program [] = { "S. Leoce, *nix(tm) tail.c"
  17.                  "v1.0 r1.0 svclvl 1 va@psj" };
  18.  
  19. static    char *Usage = "usage: tail [/hn#] [file file ...]";
  20.  
  21. #include "b:cmdline.c"
  22.  
  23. typedef    struct    qnode {            /* queue entry node          */
  24.     char *ln;            /* next line data area          */
  25.     struct  qnode *next;        /* next node in queue          */
  26. } node;
  27. static    long qsize = 0L;
  28.  
  29. int main (argc, argv)
  30. char    *argv[];
  31. int     argc;
  32. {
  33.     short    unsigned LineOption = FALSE;
  34.     short    unsigned header     = FALSE;
  35.     long    register number = DEFAULT;    /* default lines to write */
  36.     FILE    *fp;                /* file stream pointer      */
  37.     char    line [LINSIZ];            /* input line          */
  38.     node    *enqueue();            /* insert routine      */
  39.     node    *release();            /* the free routine      */
  40.  
  41.     node *front = NULL;
  42.     node *rear  = NULL;
  43.  
  44.     opterr = FALSE;
  45.     while ((LineOption = getopt(argc, argv, "hn:")) != EOF)
  46.         switch(LineOption) {
  47.         case '?':
  48.             fprintf(stderr,"tail: illegal option %c\n",badopt);
  49.             _exit (0x04);
  50.         case 'n':
  51.             number = max(atol(optarg),0);
  52.             break;
  53.         case 'h':
  54.             header = TRUE;
  55.         }    /* switch closed here */
  56.  
  57.     if (number == 0)
  58.         _exit(fprintf(stderr,"%s\n", Usage) + 0x04);
  59.  
  60.     if (argv[optind] == NULL) {    /* use like a filter now      */
  61.         while(fgets(line,LINSIZ,stdin) != NULL)
  62.             if (number > 0) {
  63.                 front = enqueue(front,number--,line);
  64.                 if (++qsize == 1)
  65.                     rear = front;
  66.                 else
  67.                     rear = rear -> next;
  68.             }
  69.             if (number == 0)
  70.                 rear -> next = front;
  71.             else {              /* move the queue down */
  72.                 rear = front;
  73.                 front = front -> next;
  74.                 strcpy(rear -> ln, line);
  75.             }
  76.         dequeue(front,qsize);
  77.     }
  78.     else {                /* do each file              */
  79.         long save = number;
  80.         while (argv[optind] != NULL) {
  81.             if (header)
  82.                 printf("--------------- %s\n",argv[optind]);
  83.             number = save;
  84.             qsize  = 0L;
  85.             if ((fp = fopen(argv[optind++], "r")) == NULL)
  86.                 _exit(perror(strcat("tail: can't open ",
  87.                     strupr(argv[optind-1]))) + 0x10);
  88.             while(fgets(line, LINSIZ, fp) != NULL)
  89.                 if (number > 0) {    /* enqueue next  */
  90.                     front = enqueue(front,number--,line);
  91.                     if (++qsize == 1)    /* rear is same */
  92.                         rear = front;
  93.                     else
  94.                         rear = rear -> next;
  95.                     if (number == 0)
  96.                         rear -> next = front;
  97.                 }                    
  98.                 else {          /* move the queue down */
  99.                     strcpy (front -> ln, line);
  100.                     rear = front;
  101.                     front = front -> next;
  102.                 }
  103.             dequeue(front,qsize);
  104.             fclose (fp);
  105.             front = rear = release(front,qsize);
  106.             printf("\n");    /* ensure the newline for next file */
  107.         }
  108.     }    /* else is closed */
  109.  
  110.     return (0);
  111. }
  112.  
  113. node *enqueue(p,n,data)
  114. node *p;
  115. char *data;
  116. long n;
  117. {
  118.     char *strwrt();
  119.  
  120.     if (p == NULL) {    /* here's the place to link ... */
  121.         if ((p = (node *) malloc(sizeof(node))) == NULL)
  122.             _exit(fprintf(stderr,
  123.                 "tail: insufficient core\n") + 0x10);
  124.         p -> ln = strwrt(data, LINSIZ);
  125.         p -> next = NULL;
  126.     }
  127.     else
  128.         p -> next = enqueue(p -> next, n, data);
  129.  
  130.     return (p);        /* return the pointer here */
  131.  
  132. }
  133.  
  134. char *strwrt(s,n)        /* save a string s somewhere in memory */
  135. char *s;
  136. unsigned n;
  137. {
  138.     char *p;
  139.  
  140.     if ((p = (char *) malloc(n+1)) != NULL)
  141.         strcpy (p, s);
  142.     else
  143.         _exit(fprintf(stderr,"tail: insufficient core\n") + 0x10);
  144.  
  145.     return (p);
  146. }
  147.  
  148. dequeue(q,n)
  149. node *q;
  150. long n;
  151. {
  152.     while (n-- > 0 && q != NULL) {
  153.         printf ("%s", q -> ln);
  154.         q = q -> next;
  155.     }
  156. }
  157.  
  158. node *release(p,s)
  159. node *p;
  160. long s;
  161. {
  162.     /* release the pointers and the node item for next time */
  163.     
  164.     auto node *q = p;
  165.  
  166.     while (s-- > 0) {
  167.         q = p -> next;
  168.         free (p -> ln);
  169.         free (p);
  170.         p = q;
  171.     }
  172.     return (NULL);
  173. }
  174.